package net.oschina.git.fsppp.dao;

import net.oschina.git.fsppp.exception.P3Exception;
import net.oschina.git.fsppp.model.P3Dir;
import net.oschina.git.fsppp.model.P3FAT;
import net.oschina.git.fsppp.utils.P3Utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by guin_guo on 2016/10/11.
 */
public class DirDao {
    public DirDao() {
    }

    public P3Dir getByPath(String path) throws Exception {
        P3Dir dir = P3Utils.getByPath(path);
        //文件夹
        if (dir != null) {
            return dir;
        }
        //文件

        return null;
    }

    public P3Dir getById(String diskName, int id) throws Exception {
        P3Dir dir = P3Utils.getById(diskName, id);
        if (dir == null) {
            throw new P3Exception("文件不存在");
        }
        return dir;
    }

    public void deleteFile(P3Dir persist) throws Exception {
        P3Utils.deleteFile(persist);
    }

    public List<P3Dir> search(P3Dir current, String key) throws Exception {
        return P3Utils.search(current, key);
    }

    public void deleteDir(P3Dir dir) throws Exception {
        P3Utils.deleteDir(dir);
    }

    public static class DefaultInstance {
        public static DirDao instance = new DirDao();
    }
    public static DirDao getInstance() {
        return DefaultInstance.instance;
    }

    /**
     * 创建文件夹
     * @param path
     * @param name
     * @return
     * @throws Exception
     */
    public P3Dir create(String path, String name) throws Exception {
        //1 判断路径是否存在
        String diskName = path.substring(0,1);
        P3FAT fat = P3Utils.getFatByDisk(diskName);
        P3Dir newDir = new P3Dir();
        if (path.split("\\\\").length > 1) {
            List<LinkedList<Integer>> fileLinks = fat.toFileLinked();
            //过滤一块的fileBlock
            List<Integer> ids = new ArrayList<>();
            fileLinks.stream().filter(v -> v.size() == 1).forEach(v -> ids.add(v.get(0)));//过滤出文件（夹）
            List<P3Dir> dirs = P3Utils.getByDiskNameAndBlockIds(diskName, ids);
            P3Dir current = null;
            for (P3Dir dir : dirs) {
                if (dir.getPath().equals(path)||(dir.getPath()+"\\").equals(path)) {
                    current = dir;
                    break;
                }
            }
            if (current == null) {
                throw new P3Exception("路径不存在");
            }
            //2 判断current路径下是否存在name的文件（夹）
            P3Dir exist = null;
            for (P3Dir dir : dirs) {
                if (dir.getPid() == current.getStartNum() && dir.getName().equals(name)) {
                    exist = dir;
                    break;
                }
            }
            if (exist != null) {
                throw new P3Exception("文件夹已存在");
            }

            newDir.setPid(current.getStartNum());
        }
        else {
            //root
            newDir.setPid(0);
        }
        //3 + Dir
        newDir.setName(name);
        newDir.setType(P3Dir.TYPE_OF_DIR);
        if (!path.endsWith("\\")) {
            path += "\\";
        }
        newDir.setPath(path + name);
        newDir.setLength(1);
        newDir.setStartNum(fat.allocate());
        return P3Utils.write2Disk(newDir,fat);
    }

    /**
     * 修改文件夹名称
     * @param dir
     * @param name 新名称
     * @return
     * @throws Exception
     */
    public P3Dir edit(P3Dir dir, String name) throws Exception {
        String path = dir.getPath();
        String diskName = path.substring(0,1);
        P3FAT fat = P3Utils.getFatByDisk(diskName);
        List<P3Dir> dirs = P3Utils.getByDiskNameAndPid(diskName, dir.getPid());

        dirs.forEach(v -> {
            if (v.getName().equals(name)) {
                throw new P3Exception("当前已存在[" + name + "]目录");
            }
        });

        dir.setName(name);
        dir.setPath(dir.getPath().substring(0, dir.getPath().lastIndexOf("\\") + 1) + name);
        return P3Utils.write2Disk(dir, fat);
    }

    /**
     * 创建文件
     * @param path
     * @param name
     * @return
     * @throws Exception
     */
    public P3Dir createFile(String path, String name) throws Exception {
        //1.获取当前目录
        P3Dir parent = P3Utils.getByPath(path);
        String[] ss = path.split("\\\\");
        if (ss.length > 1) {
            //2.检查目录是否存在，文件是否重名
            if (parent == null) {
                throw new P3Exception("路径不存在");
            }
        }
        List<P3Dir> allDirs = P3Utils.listAllDirs(path);
//        allDirs.forEach(v -> System.out.println(v.getPath()));
        P3Dir repeat = null;
        for (P3Dir v : allDirs){
            if (v.getName().equals(name)) {
                repeat = v;
            }
        }
        if (repeat != null) {
            throw new P3Exception("文件[" + name + "]已存在");
        }
        //3.创建，分配内存
        P3Dir newDir = P3Utils.createDirFile(parent, name,null);
        return newDir;
    }

    /**
     * 修改文件
     * 暂时只允许修改name，attr，content
     *
     * @param persist
     * @param dir
     * @return
     * @throws Exception
     */
    public P3Dir editFile(P3Dir persist, P3Dir dir) throws Exception {
        boolean flag = false;
        if (!persist.getName().equals(dir.getName())) {
            //改名
            String newPath = dir.getPath().substring(0, dir.getPath().lastIndexOf("\\") + 1) + dir.getName();
            dir.setPath(newPath);
            flag = true;
        }
        if ((persist.getAttr() != null) && !persist.getAttr().equals(dir.getAttr())) {
            //改属性
            String newName = dir.getName().substring(0, dir.getName().lastIndexOf(".") + 1) + dir.getAttr();
            String newPath = dir.getPath().substring(0, dir.getPath().lastIndexOf("\\") + 1) + newName;
            dir.setName(newName);
            dir.setPath(newPath);
            flag = true;
        }
        if (flag) {
            //检查重名
            String path = dir.getPath().substring(0, dir.getPath().lastIndexOf("\\"));
            List<P3Dir> allDirs = P3Utils.listAllDirs(path);
            P3Dir repeat = null;
            for (P3Dir v : allDirs) {
                if (v.getName().equals(dir.getName())) {
                    repeat = v;
                }
            }
            if (repeat != null) {
                throw new P3Exception("文件[" + dir.getName() + "]已存在");
            }
            if (dir.getPath().getBytes().length >= P3Utils.MAX_BLOCK_SIZE - 4) {
                throw new P3Exception("文件名超过限制的长度->" + (P3Utils.MAX_BLOCK_SIZE - 4));
            }
            P3Utils.editPath(dir);
            return dir;
        }
        if (!Arrays.equals(persist.getContent(), dir.getContent())) {
            //修改内容
            P3Utils.editContent(dir.getPath().substring(0, 1), persist, dir);
        }
        return dir;
    }

    /**
     * 获取文件夹下的子文件夹
     * 只获取一层，而且尚未支持文件返回
     * @param dir
     * @return
     * @throws Exception
     */
    public List<P3Dir> listByParent(P3Dir dir) throws Exception {
        String diskName = dir.getPath().substring(0, 1);
        List<P3Dir> l = P3Utils.getAllByDiskNameAndPid(diskName, dir.getStartNum());
        return l;
    }

    /**
     * 获取此路径下的子文件夹
     * @param path 绝对路径
     * @return
     * @throws Exception
     */
    public List<P3Dir> listByPath(String path) throws Exception {
        List<P3Dir> l = P3Utils.listAllDirs(path);
        return l;
    }

    public void deleteDirById(String diskName, Integer id) throws Exception {
        P3Utils.deleteDirById(diskName, id);
    }

    public void deleteByPath(Integer id) {
        //TODO
    }

}
